import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;

public class FileManager {
    //使用键值对的方式将用户名和用户进行绑定
    private Map<String, User> users;
    private User currentUser;
    private DiskManager diskManager;
    private Scanner scanner;

    public FileManager() {
        users = new HashMap<>();
        User u = new User("123","123");
        users.put("123",u);
        diskManager = new DiskManager();
        scanner = new Scanner(System.in);
    }

    //登录
    public void login() {
        //输入用户名和密码
        System.out.print("Username: ");
        String username = scanner.nextLine();
        System.out.print("Password: ");
        String password = scanner.nextLine();

        //如果已经有这个用户，直接从表中取出，赋值给user
        User user = users.get(username);
        //如果匹配成功，就将用户赋值给当前用户
        if (user != null && user.getPassword().equals(password)) {
            currentUser = user;
            //分配用户目录给用户
            currentUser.setCurrentDirectory(new Directory(currentUser.getUsername(),1));
            System.out.println("登录成功!");
        } else {
            System.out.println("账号或者密码错误！");
        }
    }

    //展示所有文件和文件夹
    public void dir() {
        //没有用户
        if (currentUser == null) {
            System.out.println("当前用户为空，请进行登录");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        //没有文件夹
        if (currentDirectory == null) {
            System.out.println("没有文件或者文件夹");
            return;
        }

        //如果上方的两个if都没进入，则使用foreach进行打印文件
        System.out.println("文件:");
        for (Map.Entry<String, File> entry : currentDirectory.getFiles().entrySet()) {
            System.out.println("文件名：" + entry.getValue().getName()+" 文件的长度："
                    + entry.getValue().getLength() + " 文件的物理地址："
                    + entry.getValue().getSize() + " 文件的保护码："
                    + entry.getValue().getSave());
        }
        //打印文件夹
        System.out.println("文件夹:");
        for (Map.Entry<String, Directory> entry : currentDirectory.getDirectories().entrySet()) {
            System.out.println(entry.getValue().getName());
        }
    }

    //创建文件
    public void create(String filename) {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        if (currentDirectory == null) {
            System.out.println("没有文件夹");
            return;
        }

        if (currentDirectory.getFile(filename) != null) {
            System.out.println("文件已经存在: " + filename);
            return;
        }

        int blockId = diskManager.allocateBlock();//分配磁盘块
        if (blockId == -1) {//如果磁盘块 == -1 证明已经没有空间了
            System.out.println("磁盘已无空间");
            return;
        }
        System.out.print("请输入文件的保护码：");
        String _save = scanner.nextLine();
        int save = Integer.parseInt(_save);
        File file = new File(filename, blockId,save);//创建文件的同时分配磁盘块
        //分配内存块和文件长度
        Random random = new Random();
        int num1 = random.nextInt(1000);
        int num2 = random.nextInt(10000);
        file.setLength(num1 + blockId);
        file.setSize(num2 + blockId);

        currentDirectory.addFile(file);//将当前文件加入当前文件夹
        System.out.println("文件已创建: " + filename);//将创建好的文件名字打印出来
    }

    //删除文件
    public void delete(String filename) {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        if (currentDirectory == null) {
            System.out.println("没有文件或者文件夹");
            return;
        }

        File file = currentDirectory.getFile(filename);
        if (file == null) {
            System.out.println("文件没有找到" + filename);
            return;
        }

        diskManager.freeBlock(file.getBlockId());//将分配给这个文件的磁盘块回收
        currentDirectory.removeFile(file);
        System.out.println("文件已删除 " + filename);
    }

    //打开文件
    public void open(String filename) {
        if (currentUser == null) {
            System.out.println("帅哥，请先登录！");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        if (currentDirectory == null) {
            System.out.println("没有文件或者文件夹");
            return;
        }

        File file = currentDirectory.getFile(filename);
        if (file == null) {
            System.out.println("文件没有找到: " + filename);
            return;
        }

        currentUser.setCurrentFile(file);//修改当前文件是哪个
        System.out.println("打开文件: " + filename);
    }

    public void close() {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        File currentFile = currentUser.getCurrentFile();
        if (currentFile == null) {
            System.out.println("没有文件被打开");
            return;
        }

        currentUser.setCurrentFile(null);
        System.out.println("被关闭的文件是: " + currentFile.getName());
    }

    //读文件
    public void read() {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        File currentFile = currentUser.getCurrentFile();
        if (currentFile == null) {
            System.out.println("没有文件被打开");
            return;
        }

        String content = diskManager.readBlock(currentFile.getBlockId());
        System.out.println("文件的内容是:");
        System.out.println(content + "  美好且魔幻的世界，继续享受人生，感受世间冷暖吧！");
    }

    //写文件
    public void write(String content) {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        File currentFile = currentUser.getCurrentFile();
        if (currentFile == null) {
            System.out.println("没有文件被打开");
            return;
        }
        if(currentFile.getSave() == 0){
            System.out.println("文件只是只读，不允许修改，非法操作，我要报警啦！");
            return;
        }
        diskManager.writeBlock(currentFile.getBlockId(), content);
        System.out.println("文件内容已更新");
    }

    //创建文件夹
    public void mkdir(String directoryName) {
        if (currentUser == null) {
            System.out.println("请先登录！");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        if (currentDirectory == null) {
            System.out.println("当前没有文件夹");
            return;
        }

        if (currentDirectory.getDirectory(directoryName) != null) {
            System.out.println("文件夹已存在: " + directoryName);
            return;
        }

        Directory directory = new Directory(directoryName,1);
        currentDirectory.addDirectory(directory);
        System.out.println("文件夹已创建: " + directoryName);
    }


    //删除文件夹
    public void remove(String directoryName) {
        if (currentUser == null) {
            System.out.println("请先登录");
            return;
        }

        Directory currentDirectory = currentUser.getCurrentDirectory();
        if (currentDirectory == null) {
            System.out.println("没有文件或者文件夹");
            return;
        }

        Directory directory = currentDirectory.getDirectory(directoryName);
        if (directory == null) {
            System.out.println("文件夹没有被找到: " + directoryName);
            return;
        }

        currentDirectory.removeDirectory(directory);
        System.out.println("文件夹已移除: " + directoryName);
    }

    public void run() {
        while (true) {
            System.out.print("> ");
            //读入命令
            String command = scanner.nextLine();
            //startsWith是String里面的一个方法，功能为匹配字符串
            if (command.startsWith("login")) {
                login();//登录
            } else if (command.startsWith("dir")) {
                dir();//展示文件夹
            } else if (command.startsWith("create")) {
                String filename = command.substring(7);//创建文件名字
                create(filename);//创建文件
            } else if (command.startsWith("delete")) {
                String filename = command.substring(7);//删除的文件名字是什么
                delete(filename);//删除文件
            } else if (command.startsWith("open")) {
                String filename = command.substring(5);
                open(filename);//打开文件
            } else if (command.startsWith("close")) {
                close();//关闭文件
            } else if (command.startsWith("read")) {
                read();//只读文件
            } else if (command.startsWith("write")) {
                String content = command.substring(6);
                write(content);//读写文件
            } else if (command.startsWith("mkdir")) {
                String directoryName = command.substring(6);
                mkdir(directoryName);//创建文件夹
            } else if (command.startsWith("remove")) {
                String directoryName = command.substring(7);
                remove(directoryName);//删除文件夹
            } else if (command.startsWith("exit")) {
                break;//退出整个系统
            } else {
                System.out.println("非法命令，请重新输入！");
            }
        }
    }

    public static void main(String[] args) {
        FileManager fileManager = new FileManager();
        fileManager.run();
    }
}

class User {
    private String username;
    private String password;
    private Directory currentDirectory;//表示当前哪个文件夹被打开或者说被使用
    private File currentFile;//表示当前哪个文件被打开或者说被使用

    public User(String username, String password) {
        this.username = username;
        this.password = password;
        this.currentDirectory = null;
        this.currentFile = null;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public Directory getCurrentDirectory() {
        return currentDirectory;
    }

    public void setCurrentDirectory(Directory currentDirectory) {
        this.currentDirectory = currentDirectory;
    }

    public File getCurrentFile() {
        return currentFile;
    }

    public void setCurrentFile(File currentFile) {
        this.currentFile = currentFile;
    }
}

class Directory {
    private String name;//文件夹名字
    private Map<String, File> files;//创建一个键值对存储文件
    private Map<String, Directory> directories;//创建一个键值对存储文件夹
    private int save;//1表示可以被读写，0表示只读

    public Directory(String name,int save) {
        this.save = save;
        this.name = name;
        this.files = new HashMap<>();
        this.directories = new HashMap<>();
    }

    public String getName() {
        return name;
    }

    public void addFile(File file) {
        files.put(file.getName(), file);
    }

    public void removeFile(File file) {
        files.remove(file.getName());
    }

    public File getFile(String filename) {
        return files.get(filename);
    }

    public void addDirectory(Directory directory) {
        directories.put(directory.getName(), directory);
    }

    public void removeDirectory(Directory directory) {
        directories.remove(directory.getName());
    }

    public Directory getDirectory(String directoryName) {
        return directories.get(directoryName);
    }

    public Map<String, File> getFiles() {
        return files;
    }

    public Map<String, Directory> getDirectories() {
        return directories;
    }
}

class File {
    private String name;//文件名
    private int blockId;//文件被放到哪个磁盘块
    private int size = 112;
    private int length = 1000;
    private int save;//1表示可以被读写，0表示只读

    public int getSave() {
        return save;
    }

    public void setSave(int save) {
        this.save = save;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public File(String name, int blockId, int save) {
        this.name = name;
        this.save = save;
        this.blockId = blockId;
    }

    public String getName() {
        return name;
    }

    public int getBlockId() {
        return blockId;
    }
}

class DiskManager {
    private static final int NUM_BLOCKS = 100;//默认的磁盘块的容量有100
    private boolean[] blocks;//创建一个boolean数组判断哪块磁盘块被使用

    //对磁盘块进行初始化，开始磁盘块都未被使用
    public DiskManager() {
        blocks = new boolean[NUM_BLOCKS];
        for (int i = 0; i < NUM_BLOCKS; i++) {
            blocks[i] = false;
        }
    }

    //磁盘块分配，找到blocks[i] = false的磁盘块分配给文件
    public int allocateBlock() {
        for (int i = 0; i < NUM_BLOCKS; i++) {
            if (!blocks[i]) {
                blocks[i] = true;
                return i;
            }
        }
        return -1;
    }

    public void freeBlock(int blockId) {
        if (blockId >= 0 && blockId < NUM_BLOCKS) {
            blocks[blockId] = false;
        }
    }

    public String readBlock(int blockId) {
        return "读这个内容在内存块id " + blockId;
    }

    public void writeBlock(int blockId, String content) {
        System.out.println("写这个内容在内存块id " + blockId + ": " + content);
    }
}

